import { Injectable, InternalServerErrorException } from '@nestjs/common';
import { UsersService } from '../users/users.service';
import { JwtService } from '@nestjs/jwt';
import { InjectModel } from '@nestjs/mongoose';
import { Auth } from './auth.schema';
import { Model } from 'mongoose';
import { PickType } from '@nestjs/swagger';
import { v4 } from 'uuid'
import { decode, getSerializeDateTime } from '@/utils/utils';
import * as md5 from 'md5'
@Injectable()
export class AuthService {
  constructor(
    private readonly jwtService: JwtService,
    private readonly usersService: UsersService,
    @InjectModel('auth') private authModel: Model<Auth>
  ) { }

  async validateUser(uName: string, uPws: string): Promise<LoginRes> {
    const username = process.env.NODE_ENV === "test" ? uName : decode(uName)
    const password = process.env.NODE_ENV === "test" ? uPws : decode(uPws)
    const thisAuth = await this.authModel.findOne().where('username', username).exec(); // 查询是否有username
    if (thisAuth && thisAuth.password === md5(process.env.MD5_SALT_HEADER + password + process.env.MD5_SALT_TAIL)) {
      return {
        status: 1,
        uuid: thisAuth.uuid
      }
    } else if (thisAuth && thisAuth.password !== password) {
      return {
        status: -1,
      }
    } else {
      return {
        status: 0,
      }
    }
  }

  // 用户登录
  async login(auth: LoginInfo) {
    let username = process.env.NODE_ENV === "test" ? auth.username : decode(auth.username)
    let password = process.env.NODE_ENV === "test" ? auth.password : decode(auth.password)
    const thisAuth = await this.authModel.findOne().where('username', username).exec(); // 查询是否有username
    if (!thisAuth) {
      throw new InternalServerErrorException({
        errMsg: '该用户名或账号不存在'
      })
    }
    password = md5(process.env.MD5_SALT_HEADER + password + process.env.MD5_SALT_TAIL)
    const thisAuth1 = await this.authModel.findOne().where('username', username).where('password', password).exec(); // 查询是否账号密码对应
    if (!thisAuth1) {
      throw new InternalServerErrorException({
        errMsg: '用户名或密码不正确'
      })
    }
    const payload = { uuid: thisAuth1.uuid, userType: thisAuth1.userType };
    return {
      access_token: this.jwtService.sign(payload),
    };
  }

  // 用户注册
  async register(newLoginInfo: LoginInfo) {
    const username = process.env.NODE_ENV === "test" ? newLoginInfo.username : decode(newLoginInfo.username)
    let password = process.env.NODE_ENV === "test" ? newLoginInfo.password : decode(newLoginInfo.password)
    const thisAuth = await this.authModel.findOne().where('username', username).exec(); // 查询是否有username
    if (thisAuth) {
      throw new InternalServerErrorException({
        errMsg: '该用户名或账号已存在'
      })
    }
    password = md5(process.env.MD5_SALT_HEADER + password + process.env.MD5_SALT_TAIL)
    const uuid = v4()
    const updateTime = getSerializeDateTime(),
      createTime = updateTime
    const newAuth = {
      username,
      password,
      uuid,
      updateTime,
      createTime,
      userType: 0,
      useStatus: 0,
    }
    const createdAuth = new this.authModel(newAuth);
    createdAuth.save(); // 插入数据库
    this.usersService.insertNewUser(newAuth as Auth)
  }

  // 修改密码
  async modifyPwd(loginInfo: modifyLoginInfo) {
    const username = process.env.NODE_ENV === "test" ? loginInfo.username : decode(loginInfo.username)
    let password = process.env.NODE_ENV === "test" ? loginInfo.password : decode(loginInfo.password)
    let newPassword = process.env.NODE_ENV === "test" ? loginInfo.newPassword : decode(loginInfo.newPassword)
    password = md5(process.env.MD5_SALT_HEADER + password + process.env.MD5_SALT_TAIL)
    newPassword = md5(process.env.MD5_SALT_HEADER + newPassword + process.env.MD5_SALT_TAIL)
    const res = await this.authModel.findOneAndUpdate({
      username: {
        $eq: username
      },
      password: {
        $eq: password
      },
      useStatus: {
        $ne: -1
      }
    }, {
      password: newPassword,
      updateTime: getSerializeDateTime()
    })
    if (!res) {
      throw new InternalServerErrorException({
        errMsg: '该用户名或账号不存在或旧密码错误'
      })
    }
  }
}

export class LoginInfo extends PickType(Auth, ['username', 'password'] as const) { } //swagger的PickType只使用list中的key

export class modifyLoginInfo extends PickType(Auth, ['username', 'password'] as const) {
  newPassword: string
}

export type LoginRes = {
  status: number,
  uuid?: string
}